在這邊我們定義了兩個物件,等等我們會用建構式的方式產生這兩個物件,並且這兩個物件繼承同一個原型。
情境呢跟上一篇文章一樣,我們是造物主,我們必須在腦海中先有狗的原型,然後創造出兩支狗,一隻叫比比,一隻叫噗噗。
var Bibi = {
name: '比比',
color: '棕色',
size: '小',
bark: function () {
console.log(this.name + '吠叫');
}
};
var Pupu = {
name: '噗噗',
color: '白色',
size: '大',
bark: function () {
console.log(this.name + '吠叫');
}
};
可以注意到這兩隻狗都具有吠叫的方法,也就是說這個方法我們可以定義在這兩隻狗的藍圖上,也就是他們的原型函式。
那麼我們就來定義吧!
我們再定義屬性的時候,會利用 this.屬性名稱 = 屬性
的方式定義,這樣在使用 new 的時候就可以客製化的傳入不同的進近來,賦予不同的屬性內容。
function Dog (name, color, size) {
this.name = name;
this.color = color;
this.size = size;
}
所以一開始會是這樣~!
現在 Dog 的函式只是一個藍圖,它並不是一個實體,要讓它變成實體我們就需要使用到 new 的這個運算子。
那麼首先我們先來看一下這個運算子的相關文件
MDN 的文件這邊提到,使用 new 運算子會產生一個 Javascript 的物件,並且會連結回原本的物件(在這邊的例子也就是指說被 new 出來的實體會連結到原本的 Dog 的函式)。
另外也會把 this 指向到新產生的實體上。
那我們就直接來實際做做看!
function Dog (name, color, size) {
this.name = name;
this.color = color;
this.size = size;
}
var Bibi = new Dog('比比','棕色', '小');
console.log('Bibi', Bibi);
運行結果如下:
可以看到印出來之後,展開 Bibi 的 proto
之後,其中的 constructor 屬性指向了 Dog 的函式。代表這個物件是由 Dog 這個函示所創建的!
那麼再來我們一樣創建噗噗這隻狗
var Pupu = new Dog('噗噗','白色', '大');
console.log('Pupu', Pupu);
好~現在我們兩隻狗都創建出來了,但是你會發現還少了吠叫的方法。
這時候就要用我們上一篇文章提到的 prototype 的方法將共用的函式方法掛載到 原型上,也就是 Dog 的原型。
首先我們先 console.dir(Dog);
觀察一下狗這個函式,我們之前也有說過,函示本身就是一個物件。
所以函式裡面有一個通用的屬性叫做 prototype,
透過 prototype 所新增的方法呢,就會作為原型上的屬性,可以被向下的其他原型或是實體給取用到。
所以我們就透過將 bark 這個函式掛載在 Dog 這個原型的 prototype 上:
function Dog (name, color, size) {
this.name = name;
this.color = color;
this.size = size;
}
// 多了這裡喔!!!!!!!
Dog.prototype.bark = function () {
console.log(this.name + '吠叫');
}
// 多了這裡喔!!!!!!!
var Bibi = new Dog('比比','棕色', '小');
console.log('Bibi', Bibi);
var Pupu = new Dog('噗噗','白色', '大');
console.log('Pupu', Pupu);
之後點開來看,這兩隻狗都可以找到 bark 的吼叫功能。
那麼我們就實際的來吼叫看看!!
Bibi.bark();
Pupu.bark();
好~到這邊我們來總結一下,Dog 這個函式又被稱為建構函式,用於建構其他實體所用的。
而為什麼我們需要把 bark 的方法掛載在 Dog 的 prototype上呢? 主要是因為如果一直撰寫在不同的物件中,會消耗記憶體的容量,當你需要記載的函式越來越多的時候,記憶體的負擔就會更大。
所以透過統一掛載在 Dog 的 prototype上,可以提高效率,也方便作修改,一次只要調整一個地方就好,對於程式碼來說也是很好維護的做法。
那麼在這邊在說明一件事,上一篇文章我們是直接將方法掛載在 proto
的屬性上,但其實這個屬性是用來指向該物件的原型是誰的一個屬性。
如果我們要將共用的函式掛載在原型上的話,最好還是使用
建構函式名稱.prototype.共用函式名稱 = function (params) {
...
}
這樣的方法會比較好喔!
雖然呢
console.log(Dog.prototype === Bibi.__proto__); // true
這樣兩個內容式一樣的,但還是希望大家使用 prototype 去掛載需要用到的共用函式,同時你在除錯的時候,也比較容易找到問題點在哪裡喔!
今天就先這樣啦~希望這篇文章對大家有幫助~汪汪!